﻿using System;
using System.Collections.Generic;
using System.Linq;
using EzDesk.Core.Data;
using EzDesk.Core.Interface;
using EzDesk.Core.Model;
using EzDesk.Utility;

namespace EzDesk.Core.ServiceImpl.Services
{
    public partial class CoreService: ICoreService
    {
        readonly string MEMBERSTRING_EVERYONE = "everyone";

        #region [ Group Methods ]

        Group ICoreService.CreateGroup(SimpleUser[] users, Group[] groups, string descrition, int type)
        {
            return EzDeskDatabaseContainer.GoAndSave(
                container =>
                    {
                        var group = new Group();
                        group.Id = Guid.NewGuid();

                        List<string> ids = new List<string>();
                        ids.Add(users.Join(",", u => u.Id.ToString()));
                        ids.AddRange(groups.ToStringArrary(g => g.Id.ToString()));
                        group.Memberstring = ids.Join("|");

                        if (string.IsNullOrEmpty(descrition))
                        {
                            group.Description = users.Join(";", u => u.UserName) + groups.Join(";", g => g.Description);
                        }
                        else
                        {
                            group.Description = descrition;
                        }
                        group.Type = type;

                        container.GroupSet.AddObject(group);
                        return group;
                    });
        }

        void ICoreService.DeleteGroup(Guid groupId)
        {
            EzDeskDatabaseContainer.GoAndSave(
                container =>
                    {
                        var group = container.GroupSet.FirstOrDefault(p => p.Id == groupId);
                        if (group != null)
                        {
                            container.GroupSet.DeleteObject(group);
                        }
                    });

        }

        void ICoreService.ChangeGroupDescription(Guid groupId, string description)
        {
            EzDeskDatabaseContainer.GoAndSave(
                container =>
                    {
                        var group = container.GroupSet.FirstOrDefault(p => p.Id == groupId);
                        if (group != null)
                        {
                            group.Description = description;
                        }
                    });

        }

        IList<Group> ICoreService.GetAllSystemGroups()
        {
            return EzDeskDatabaseContainer.Go(
                container => container.GroupSet.Where(p => p.Type == 0).ToList());
        }

        public Group GetSystemGroup(string systemGroupName)
        {
            return EzDeskDatabaseContainer.Go(
                container => container.GroupSet.FirstOrDefault(p => p.Memberstring == systemGroupName && p.Type == 0));
        }

        Group ICoreService.GetGroupById(Guid groupId)
        {
            return self.GetGroups(
                convertSingleIdToIdCollection(groupId)
                )
                .FirstOrDefault();
        }


        Group ICoreService.GetGroupByName(string groupName)
        {
            return EzDeskDatabaseContainer.Go(
                container => container.GroupSet.FirstOrDefault(p => p.Name == groupName));
        }

        IList<Group> ICoreService.GetGroups(string groupIdStrs)
        {
            return self.GetGroups(
                convertIdStrsToIdCollection(groupIdStrs)
                );
        }
        IList<Group> ICoreService.GetGroups(Guid[] groupIdCollection)
        {
            return EzDeskDatabaseContainer.Go(
                container =>
                    {
                        IList<Group> groupList = new List<Group>();
                        foreach (var gid in groupIdCollection)
                        {
                            var group = container.GroupSet.FirstOrDefault(p => p.Id == gid);
                            if (group != null)
                            {
                                groupList.Add(group);
                            }
                        }
                        return groupList;
                    });

        }

        IDictionary<Guid, string> ICoreService.GetChildrenByMemberstring(string memberString)
        {
            Dictionary<Guid, string> result = new Dictionary<Guid, string>();

            // memberstring 是everyone的特殊情况
            if (memberString == MEMBERSTRING_EVERYONE)
            {
                // 添加everyone组
                result.Add(
                    self.GetSystemGroup(MEMBERSTRING_EVERYONE).Id,
                    "group"
                );
            }
            else
            {
                var members = memberString.Split('|');
                if (members.Length > 0)
                {
                    var users = members[0].Split(',');
                    foreach (var user in users)
                    {
                        Guid userId = Guid.Empty;
                        if (Guid.TryParse(user, out userId))
                        {
                            result.Add(userId, "user");
                        }
                    }
                }
                if (members.Length > 1)
                {
                    var groups = members[1].Split(',');
                    foreach (var group in groups)
                    {
                        Guid groupId = Guid.Empty;
                        if (Guid.TryParse(group, out groupId))
                        {
                            result.Add(groupId, "group");
                        }
                    }
                }
            }

            return result;
        }

        IList<SimpleUser> ICoreService.GetAllUsersInGroup(Guid groupId)
        {
            Group group = self.GetGroupById(groupId);
            return self.GetAllUsersByMemberString(group.Memberstring);
        }        
        IList<Guid> ICoreService.GetAllUserIdsByMemberString(string memberString)
        {
            return getAllUserIdsByMemberString(memberString);
        }
        IList<SimpleUser> ICoreService.GetAllUsersByMemberString(string memberString)
        {
            return
                self.GetSimpleUserInfos(
                    self.GetAllUserIdsByMemberString(memberString).ToArray()
                    );
        }

        public IList<Group> GetUserInGroups(Guid userId, int groupType = -1)
        {
            return EzDeskDatabaseContainer.Go(
                container =>
                    {
                        IList<Group> result = new List<Group>();
                        //todo: 重构 用缓存解决这里的性能问题
                        IQueryable<Group> groups = container.GroupSet;
                        if (groupType >= 0) 
                        {
                            // 不是系统组
                            groups = groups.Where(p => p.Type == groupType);
                        }
                        
                        foreach (var group in groups)
                        {
                            if (IsMemberstringContainUser(userId, group.Memberstring))
                            {
                                result.Add(group);
                            }
                        }
                        return result;
                    });
            
        }

        public bool IsUserInGroup(Guid userId, Guid groupId)
        {
            Group group = self.GetGroupById(groupId);
            return IsMemberstringContainUser(userId, group.Memberstring);
        }

        private bool IsMemberstringContainUser(Guid userId, string memberstring)
        {
            return self.GetAllUserIdsByMemberString(memberstring).Contains(userId);
        }

        void ICoreService.AddUserInGroup(Guid targetGroupId, Guid userId)
        {
            EzDeskDatabaseContainer.GoAndSave(
                container =>
                    {
                        var group = container.GroupSet.FirstOrDefault(p => p.Id == targetGroupId);
                        if (String.IsNullOrEmpty(group.Memberstring))
                        {
                            group.Memberstring = userId.ToString();
                        }
                        else
                        {
                            group.Memberstring = String.Format("{0},{1}", userId.ToString(), group.Memberstring);
                        }
                    });
        }
        void ICoreService.AddGroupInGroup(Guid targetGroupId, Guid groupId)
        {
            EzDeskDatabaseContainer.GoAndSave(
                container =>
                    {
                        var group = container.GroupSet.FirstOrDefault(p => p.Id == targetGroupId);
                        group.Memberstring = string.Format("{0},{1}", group.Memberstring, groupId);
                    });
        }

        void ICoreService.RemoveUserFromGroup(Guid targetGroupId, Guid userId)
        {
            EzDeskDatabaseContainer.GoAndSave(
                container =>
                {
                    var group = container.GroupSet.FirstOrDefault(p => p.Id == targetGroupId);
                    string[] groupIds = group.Memberstring.Split('|');
                    List<string> userIds = groupIds[0].Split(',').ToList();
                    userIds.Remove(userId.ToString());
                    groupIds[0] = String.Join(",", userIds.ToArray());
                    group.Memberstring = string.Join("|", groupIds);
                });
        }

        void ICoreService.RemoveGroupFromGroup(Guid targetGroupId, Guid groupId)
        {
            EzDeskDatabaseContainer.GoAndSave(
                container =>
                {
                    var group = container.GroupSet.FirstOrDefault(p => p.Id == targetGroupId);

                    List<string> groupIds = group.Memberstring.Split('|').ToList();
                    groupIds.Remove(groupId.ToString());
                    group.Memberstring = string.Join("|", groupIds.ToArray());
                });
        }

        #endregion


        #region [ private methods ]

        IList<Guid> getAllUserIdsByMemberString(string memberString)
        {
            return EzDeskDatabaseContainer.Go(
                container =>
                    {
                        var userIds = new List<Guid>();
                        if (string.IsNullOrEmpty(memberString)) return userIds;

                        if (memberString == MEMBERSTRING_EVERYONE)
                        {
                            // 所有人
                            userIds = container.UserProfileSet.Select(p => p.Id).ToList();
                        }
                        else
                        {
                            string[] strs = memberString.Split('|');

                            if (strs.Length > 0)
                            {
                                if (!string.IsNullOrEmpty(strs[0]))
                                {
                                    // memberstring中的userIds数据
                                    userIds = strs[0]
                                        .Split(',')
                                        .Select(p => new Guid(p))
                                        .ToList();
                                }
                            }

                            if (strs.Length > 1)
                            {
                                // 取得memberstring中包含的groups
                                var groups = self.GetGroups(strs[1]);

                                foreach (var group in groups)
                                {
                                    userIds = userIds.Union(
                                        getAllUserIdsByMemberString(group.Memberstring))
                                        .ToList();
                                }
                            }
                        }
                        return userIds.Distinct().ToList();
                    });
        }

        #endregion
    }
}

    
